package net.sunofbeach.blog.controller.admin;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sunofbeach.blog.pojo.Article;
import net.sunofbeach.blog.pojo.User;
import net.sunofbeach.blog.pojo.query.ArticleQuery;
import net.sunofbeach.blog.response.Result;
import net.sunofbeach.blog.response.ResultEnum;
import net.sunofbeach.blog.service.ArticleService;
import net.sunofbeach.blog.service.UserService;
import net.sunofbeach.blog.utils.Constants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Bing
 * @since 2021-11-24
 */
@Api(tags = "文章管理")
@RestController
@RequestMapping("/admin/article")
public class ArticleAdminApi {

    @Resource
    private UserService userService;

    @Resource
    private ArticleService articleService;

    /**
     * 添加文章
     * 后期可以做定时发布的功能
     * 如果是多人博客系统，考虑审核 一一》 成功，通知 /  审核不通过，也可通知
     * 保存草稿：
     * 1、用户手动提交：会发生页面跳转 一一》 提交完即可
     * 2、代码自动提交，每隔一段时间就会提交 一一》不会发生页面跳转 一一》 多次提交 一一》 如果没有唯一标识，就会添加到数据库里
     * 不管是哪种草稿 一一》 必须有标题
     * <p>
     * 方案一：
     * 每次用户发新文章之前 一一》 先向后台请求一个唯一文章ID
     * 如果是更新文章，同，则不需要请求空上唯一ID
     * <p>
     * 方案二：
     * 可以直接提交，后台判断有没有ID，如果没有ID，就新创建，并且ID作为此次返回的结果
     * 如果有ID，就修改已经存在的内容。
     * <p>
     * 推荐做法：
     * 自动保存草稿，在前端本地完成，也就是保存在本地
     * 如果是用户手动提交的，就提交到后台
     * <p>
     * 防止重复提交（网络卡顿的时候，用户点了几次提交）
     * 可以通过ID的方式
     * 通过token_key的提交频率来计算，如果30秒之内有多次提交，只有最前的一次有效
     * 其他的提交，直接return，提示用户不要太频繁操作
     * <p>
     * 前端的处理，点击了提交之后，禁止按钮使用，等到有响应结果，再改变按钮的状态。
     *
     * @return
     */
    @ApiOperation("新增文章")
    @PostMapping
    public Result addArticle(@RequestBody Article article) {
        return articleService.addArticle(article);
    }


    /**
     * 文章列表
     *
     * @return
     */
    @ApiOperation("条件分页查询文章")
    @PreAuthorize("@permission.admin()")
    @GetMapping("/list/{page}/{size}")
    public Result listArticle(@PathVariable("page") int page, @PathVariable("size") int size, ArticleQuery query) {
        Page<Article> pageParam = new Page<>(page, size);
        IPage<Article> pageModel = articleService.selectPage(pageParam, query);
        return Result.ok(pageModel);
    }


    /**
     * 如果有审核机制：审核中的文章 一一》只有管理员和作者自己可以获取
     * 有草稿、删除、置顶的、已经发布的
     * 删除的不能获取，其他都可以获取
     *
     * @param articleId
     * @return
     */
    @ApiOperation("根据ID查询文章详情")
    @GetMapping("/{articleId}")
    public Result getArticle(@PathVariable("articleId") String articleId) {
        if (StringUtils.isEmpty(articleId)) {
            return Result.fail().message("文章ID不能为空");
        }
        return articleService.getByArticleId(articleId);
    }


    /**
     * 更新
     * 该接口只支持修改内容：标题、内容、标签、分类、摘要
     *
     * @param article
     * @return
     */
    @ApiOperation("更新文章")
    @PutMapping
    public Result updateArticle(@RequestBody Article article) {
        // 检验当前操作用户的身份
        User currentUser = userService.checkSobUser();
        if (currentUser == null) {
            // 账号未登录
            return Result.build(null, ResultEnum.ACCOUNT_NOT_LOGIN);
        }
        // 判断数据
        if (StringUtils.isEmpty(article.getId())) {
            return Result.fail().message("文章ID不能为空");
        }
        if (StringUtils.isEmpty(article.getTitle())) {
            return Result.fail().message("文章标题不能为空");
        }
        if (StringUtils.isEmpty(article.getSummary())) {
            return Result.fail().message("文章摘要不能为空");
        }
        if (StringUtils.isEmpty(article.getLabel())) {
            return Result.fail().message("文章标签不能为空");
        }
        if (StringUtils.isEmpty(article.getContent())) {
            return Result.fail().message("文章内容不能为空");
        }
        if (StringUtils.isEmpty(article.getCategoryId())) {
            return Result.fail().message("文章分类不能为空");
        }
        // 后改
        boolean result = articleService.updateById(article);
        // 返回结果
        return result ? Result.ok().message("文章更新成功") : Result.fail().message("文章更新失败");
    }


    /**
     * 真删除
     * 如果是多用户，用户不可以删除，删除只是修改状态
     * 管理员可以删除
     *
     * @param articleId
     * @return
     */
    @ApiOperation("物理删除文章")
    @DeleteMapping("/{articleId}")
    public Result deleteArticle(@PathVariable("articleId") String articleId) {
        // 检验当前操作用户的身份
        User currentUser = userService.checkSobUser();
        if (currentUser == null) {
            // 账号未登录
            return Result.build(null, ResultEnum.ACCOUNT_NOT_LOGIN);
        }
        if (StringUtils.isEmpty(articleId)) {
            return Result.fail().message("该文章不存在");
        }
        boolean result = articleService.removeById(articleId);
        return result ? Result.ok().message("删除文章成功") : Result.fail().message("该文章不存在");
    }



    @ApiOperation("逻辑删除文章")
    @DeleteMapping("/delete/{articleId}")
    public Result delete(@PathVariable("articleId") String articleId) {
        if (StringUtils.isEmpty(articleId)) {
            return Result.fail().message("文章ID不能为空");
        }
        // 假删除，只是将状态更新
        return articleService.updateStatus(articleId,Constants.Article.STATE_DELETE);
    }


    /**
     * 置顶 / 取消置顶
     *
     * @param articleId
     * @return
     */
    @ApiOperation("文章置顶/取消置顶")
    @PutMapping("/top/{articleId}")
    public Result topArticle(@PathVariable("articleId") String articleId) {
        if (StringUtils.isEmpty(articleId)) {
            return Result.fail().message("文章ID不能为空");
        }
        // 将状态值更新为 3 置顶
        return articleService.updateStatus(articleId,Constants.Article.STATE_TOP);
    }


    /**
     * 取消置顶
     *
     * @param articleId
     * @return
     */
    @ApiOperation("取消文章置顶")
    @PutMapping("/topNo/{articleId}")
    public Result topNoArticle(@PathVariable("articleId") String articleId) {
        if (StringUtils.isEmpty(articleId)) {
            return Result.fail().message("文章ID不能为空");
        }
        // 将状态值更新为 1 发布
        return articleService.updateStatus(articleId,Constants.Article.STATE_PUBLISH);
    }



}

